######################################################################
# Time-stamp: <05/09/09 11:06:26 ostolop>
#
# Package: EP::Common::DBI::Session
#
# DBI object mapping to the *sessions* table
######################################################################
package EP::Common::DBI::Session;

use strict;
use base qw ( EP::Common::DBI );

use EP::Config;
use Data::UUID;

use EP::Common::DBI::Dataset;
use EP::Common::DBI::Folder;
use EP::Common::DBI::Action;

use Class::DBI::AbstractSearch;

EP::Common::DBI::Session->table ( 'ep_session' );
EP::Common::DBI::Session->columns ( Primary   => qw ( id ) );
EP::Common::DBI::Session->columns ( Essential => qw ( create_date expire query_id owner status current_folder current_root_dataset current_action current_cluster_selection current_metadata_selection ) );

EP::Common::DBI::Session->has_a ( owner => 'EP::Common::DBI::User' );

EP::Common::DBI::Session->has_a ( current_folder => 'EP::Common::DBI::Folder',
				  inflate => sub { my $id = shift; EP::Common::DBI::Folder->retrieve ( $id ); } );
EP::Common::DBI::Session->has_a ( current_action => 'EP::Common::DBI::Action',
				  inflate => sub { my $id = shift; EP::Common::DBI::Action->retrieve ( $id ); } );
EP::Common::DBI::Session->has_a ( current_root_dataset => 'EP::Common::DBI::Dataset',
				  inflate => sub { my $id = shift; EP::Common::DBI::Dataset->retrieve ( $id ); } );

EP::Common::DBI::Session->add_trigger ( before_create => sub {
					  my $self = shift;
					  $self->autoupdate(0);
					  $self->id ( $self->_generate_session_id );
					  $self->expire ( time() + ( $EP::Config::h->{EXPIRE_SESSION} * 60 * 60 ) );
					  $self->autoupdate(1);
					} );

EP::Common::DBI::Session->add_trigger ( after_delete  => \&_cleanup_end_session );
EP::Common::DBI::Session->autoupdate(1);

# Sub: expired
#   Returns 1 if session has expired, 0 otherwise. If it hasn't expired, extends expiration by $EP::Config::h->{EXPIRE_SESSION} hours.
sub expired {
  my $self = shift;

  return 1 if time() >= $self->expire;

  $self->keep_alive();
  return 0;
}

# Sub: keep_alive
#   Keeps session alive for another $EP::Config::h->{EXPIRE_SESSION} hours from now.
sub keep_alive {
  my $self = shift;

  $self->expire ( time() + ( $EP::Config::h->{EXPIRE_SESSION} * 60 * 60 ) );
}


# Sub: validate_session_id
#   Static class method to validate generated IDs. For now disabled.
# (code)
# sub validate_session_id {
#  my ($session_id) = @_;
#
#  die "Invalid session id ($session_id)!" if $session_id !~ /^[A-F0-9]{32}$/;
# }
# (end)

# Sub: _cleanup_end_session
#   Cleans up when session object is killed...
sub _cleanup_end_session {
  my $self = shift;

  unlink ( "$EP::Config::h->{LOG}/session_log." . $self->id . ".xml" ) or warn "Couldn't remove session log! $!\n";

  # if it is a regular user session, on log out remember the "current" locations for next log-in
  if ( $self->owner && $self->owner->username ne "guest" ) {
    $self->owner->last_root_dataset ( $self->current_root_dataset );
    $self->owner->last_folder ( $self->current_folder );
    $self->owner->last_action ( $self->current_action );
  }
}

# Sub: _generate_session_id
#   Generates a 32-character long session ID (a UUID)
sub _generate_session_id {
  my $ug = new Data::UUID;
  my $uuid = substr ( $ug->create_hex (), 2, 32 );

  return $uuid;
}

1;
